package utils

/**
 *   每个Type一个文件存储
 */

import (
	"path"
	"sync"
)

type LoggerTypeFileWriter struct {
	typeMap     sync.Map
	filenamefmt string
	fileext     string
	taskWorker  *MultiGroupTask

	// The logging format
	format        string
	logLvl        LogLevel
	logLvlOp      LogOp // 0:= 1:>=, 2:<=
	max_file_size int64
	cache_size    int64 // <=0 不使用缓存
}

func NewLoggerTypeFileWriter(fnamefmt string) *LoggerTypeFileWriter {
	rval := &LoggerTypeFileWriter{
		filenamefmt:   fnamefmt,
		format:        "[%D %T] [%L] %M (%S)\r\n",
		taskWorker:    NewMultiGroupTask(),
		logLvl:        LogLV_0,
		logLvlOp:      LogOp_ALL,
		max_file_size: 0,
	}
	rval.ConfigFileFormat(fnamefmt)
	rval.taskWorker.ConfigWorkType(2)
	rval.taskWorker.ConfigMinWork(1)
	rval.taskWorker.ConfigMaxWork(8)
	rval.taskWorker.Start()
	initializePool_loggerTypeFileRec()
	return rval
}

func (this *LoggerTypeFileWriter) ConfigFileFormat(filefmt string) *LoggerTypeFileWriter {
	this.fileext = path.Ext(filefmt)
	this.filenamefmt = DeleteFileNameExt(filefmt)
	return this
}

func (this *LoggerTypeFileWriter) GetWorkStatus() string {
	return this.taskWorker.StatusSimpleString()
}

func (this *LoggerTypeFileWriter) GetCacheSize() int {
	return int(this.cache_size)
}

func (this *LoggerTypeFileWriter) SetMsgFormat(fmt string) *LoggerTypeFileWriter {
	if this.format != fmt {
		this.format = fmt
	}
	return this
}

func (this *LoggerTypeFileWriter) SetLvlFilter(lvl LogLevel, matchOp LogOp) *LoggerTypeFileWriter {
	this.logLvl = lvl
	this.logLvlOp = matchOp
	return this
}

func (this *LoggerTypeFileWriter) ConfigMaxFileSize(val int64) *LoggerTypeFileWriter {
	this.max_file_size = val
	return this
}

func (this *LoggerTypeFileWriter) ConfigFileCacheSize(val int64) *LoggerTypeFileWriter {
	this.cache_size = val
	return this
}

func (this *LoggerTypeFileWriter) checkGetFileRec(rec *LogRecord) *loggerTypeFileRec {
	rval := getFileRecFromPool()
	rval.typestr = rec.Typestr
	rval.owner = this

	tmp, loaded := this.typeMap.LoadOrStore(rec.Typestr, rval)
	if loaded {
		rval.Release2Pool()
		rval = tmp.(*loggerTypeFileRec)
	} else {
		// 新建
		rval.typestr = rec.Typestr
	}
	return rval
}

func (this *LoggerTypeFileWriter) LogWrite(rec *LogRecord) {
	if !IsFilter(this.logLvl, this.logLvlOp, rec) {
		return
	}

	typeRec := this.checkGetFileRec(rec)
	this.taskWorker.PostTaskArgs(rec.Typestr, typeRec.onTaskLogRec, rec)
}

func (this *LoggerTypeFileWriter) Close() {
	this.taskWorker.Stop()
	this.typeMap.Range(func(key, value interface{}) bool {
		typeRec := value.(*loggerTypeFileRec)
		typeRec.Close()
		typeRec.Release2Pool()
		this.typeMap.Delete(key)
		return true
	})
}
